package com.xjgc.convert.param;

import com.alibaba.fastjson.JSON;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.core.JVM;
import com.thoughtworks.xstream.io.xml.StaxDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import com.xjgc.msibase.entity.MsiExoTask;
import org.apache.commons.lang.StringUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: 小逗号
 * @date: 2023-12-29
 * @description:
 * @since:
 */
public class ConvertParamFactory {
    private final static XStream xStream = new XStream(new StaxDriver(new XmlFriendlyNameCoder("_-", "_")));
    private final static Map<String, Class> CLASS_MEMORY = new HashMap<>(16);

    static {
        //忽略未知标签
        xStream.ignoreUnknownElements();
//        xStream.processAnnotations(new Class[]{ConvertParam.class, XmCee.class, FrzzCee.class});
        xStream.processAnnotations(ConvertParam.class);
        //xStream.alias("REQUEST_DATA", ConvertParam.class);
    }

    private static void xStreamSetting(String rootElement, String dataListElement, Class dataClass, String dataElement) {
        //数据对应的bean class加入扫描
        xStream.processAnnotations(dataClass);
        //根节点 别名 ConvertParam.class
        xStream.alias(rootElement, ConvertParam.class);
        if (StringUtils.isBlank(dataListElement)) {
            //ConvertParam.class 字段  List<T> dataList 设置,隐藏List只暴露内部元素<T>,并内部元素<T>进行别名 ITEM
            xStream.addImplicitCollection(ConvertParam.class, "dataList", dataElement, dataClass);
        } else {
            //ConvertParam.class 字段 C List<T> dataList 设置,别名 ITEMS
            xStream.aliasField(dataListElement, ConvertParam.class, "dataList");
            //List<T> dataList 内部元素 别名 ITEM
            xStream.alias(dataElement, dataClass);
        }
    }

    /**
     * 解析XML 不展示List节点
     *
     * @param rootElement 根节点名
     * @param dataClass   data class
     * @param dataElement 数据节点名
     * @param xml         xml
     * @param <T>
     * @return
     */
    private static <T extends Serializable> ConvertParam<T> parseXml(String rootElement, Class<T> dataClass, String dataElement, String xml) {
        return ConvertParamFactory.parseXml(rootElement, null, dataClass, dataElement, xml);
    }

    /**
     * 解析XML
     *
     * @param rootElement     根节点名
     * @param dataListElement List节点名,null时跳过list直接暴露内部元素节点
     * @param dataClass       data class
     * @param dataElement     数据节点名
     * @param xml             xml
     * @param <T>
     * @return
     */
    public static <T extends Serializable> ConvertParam<T> parseXml(String rootElement, String dataListElement, Class<T> dataClass, String dataElement, String xml) {
        xStreamSetting(rootElement, dataListElement, dataClass, dataElement);
        Object o = xStream.fromXML(xml);
        return (ConvertParam<T>) o;
    }


    public static ConvertParam parseXml(MsiExoTask exoTask, String xml) {
        String rootElement = exoTask.getRootElement();
        String dataListElement = exoTask.getDataListElement();
        String dataElement = exoTask.getDataElement();
        String paramBean = exoTask.getParamBean();
        Class beanClass = getClass(paramBean);
        return parseXml(rootElement, dataListElement, beanClass, dataElement, xml);
    }

    private static Class getClass(String className) {
        if (CLASS_MEMORY.containsKey(className)) {
            return CLASS_MEMORY.get(className);
        }
        Class aClass = JVM.loadClassForName(className);
        CLASS_MEMORY.put(className, aClass);
        return aClass;
    }

    public static <T extends Serializable> ConvertParam<T> parseJson(Class<T> dataClass, String jsonString) {
        ConvertParam convertParam = JSON.parseObject(jsonString, ConvertParam.class);
        List dataList = convertParam.getDataList();
        List list = new ArrayList();
        for (Object o : dataList) {
            Object javaObject = JSON.toJavaObject((JSON) o, dataClass);
            list.add(javaObject);
        }
        convertParam.setDataList(list);
        return convertParam;

    }

    public static ConvertParam parseJson(String dataClass, String jsonString) {
        Class aClass = getClass(dataClass);
        ConvertParam convertParam = parseJson(aClass, jsonString);
        return convertParam;
    }

    public static String toXml(MsiExoTask exoTask, ConvertParam convertParam) {
        String rootElement = exoTask.getRootElement();
        String dataListElement = exoTask.getDataListElement();
        String dataElement = exoTask.getDataElement();
        String paramBean = exoTask.getParamBean();
        Class beanClass = getClass(paramBean);
        String xml = toXml(rootElement, dataListElement, beanClass, dataElement, convertParam);
        return xml;
    }

    private static String toXml(String rootElement, String dataListElement, Class dataClass, String dataElement, ConvertParam convertParam) {
        xStreamSetting(rootElement, dataListElement, dataClass, dataElement);
        String xml = xStream.toXML(convertParam);
        return xml;

    }
}
